#include "xpath_static.h"
#include "tinyxml.h"
#include "user.h"
#include "logger.h"
#include "login_manager.h"
#include "exception_xml.hpp"

LoginManager::LoginManager( const std::string& sFilePath ) throw( utils::Exception )
:
	m_sFilePath( sFilePath )
{
	Reload();
}

LoginManager::~LoginManager()
{
	Clear();
}

void LoginManager::Clear()
{
	for( UserMap::iterator it = m_mapUsers.begin(); it != m_mapUsers.end(); ++it )
	{
		delete it->second;
	}
	m_mapUsers.clear();
}

//TODO is this method used? If not, it should be removed 
std::string LoginManager::GetFilePath()
{
	return m_sFilePath;
}

//TODO rename Search to ... GetUser
User* LoginManager::Search( std::string sName ) throw( utils::Exception )
{
	UserMap::iterator it = m_mapUsers.find( sName );
	if( it == m_mapUsers.end() )
	{
		return NULL;
	}

	return it->second;
}

void LoginManager::Reload() throw( utils::Exception )
{
	Clear();

	TiXmlDocument xmlDoc;
	xmlDoc.LoadFile( m_sFilePath.c_str() );
	        if( xmlDoc.Error() )
    {
        DBG << "Error loading XML file '" << m_sFilePath << "' at [ "
            << xmlDoc.ErrorRow() << ", "
            << xmlDoc.ErrorCol() << " ]: "
            << xmlDoc.ErrorDesc() << std::endl;

		throw utils::ExceptionXml( "Wrong Database Config XML" );
    }

    TiXmlElement* pRootElement = xmlDoc.RootElement();
    if( NULL == pRootElement )
    {
        throw utils::ExceptionXml( "Cannot get Database Config XML root element" );
    }

    for( TiXmlElement* pUserElement = pRootElement->FirstChildElement( "user" );
		 NULL != pUserElement;
		 pUserElement = pUserElement->NextSiblingElement( "user" ) )
	{
		User* pUser = new User( pUserElement );
		DBG << "User created successfully: " << pUser->GetName() << std::endl;
		m_mapUsers.insert( std::make_pair( pUser->GetName(), pUser ) );

	}

	if( m_mapUsers.empty() )
	{
		throw( utils::Exception( "No users in database!" ) );
	}
}

std::string LoginManager::GetAvailableUsers()
{
	std::stringstream ssFNs;
	for( UserMap::const_iterator cit = m_mapUsers.begin();
		 cit != m_mapUsers.end();
		 ++cit )
	{
		ssFNs << cit->first << " ";
	}

	return ssFNs.str();
}

